package com.itheima.app.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.mongo.Comment;
import com.itheima.domain.mongo.FocusUser;
import com.itheima.domain.mongo.Video;
import com.itheima.domain.vo.CommentVo;
import com.itheima.domain.vo.PageBeanVo;
import com.itheima.domain.vo.VideoVo;
import com.itheima.service.db.Logger;
import com.itheima.service.mongo.CommentService;
import com.itheima.service.mongo.FocusService;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.mongo.VideoService;
import com.itheima.util.ConstantUtil;
import org.apache.dubbo.config.annotation.Reference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Component
public class VideoManager {

    @Reference
    private VideoService videoService;
    @Reference
    private UserInfoService userInfoService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private FastFileStorageClient client;  //存储的客户端  注入会报错 , 不影响执行
    @Autowired
    private FdfsWebServer webServer; // tracker的服务器  注入会报错 , 不影响执行
    @Autowired
    private OssTemplate ossTemplate;
    @Reference
    private FocusService focusService;
    @Reference
    private CommentService commentService;

    /**
     * 查询小视频列表
     *
     * @param page     页码
     * @param pageSize 每页条数
     */
    public PageBeanVo videoList(Integer page, Integer pageSize) {
        //获取登录用户id
        Long userId = UserHolder.getId();
        //查询小视频列表
        PageBeanVo pageBeanVo = videoService.findVideoList(page, pageSize, userId);
        //获取视频列表
        List<Video> items = (List<Video>) pageBeanVo.getItems();
        List<VideoVo> videoVoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(items)) {
            for (Video video : items) {
                VideoVo videoVo = new VideoVo();
                UserInfo userInfo = userInfoService.findById(video.getUserId());
                BeanUtil.copyProperties(userInfo, videoVo);
                BeanUtil.copyProperties(video, videoVo);
                videoVo.setCover(video.getPicUrl());
                videoVo.setSignature("青山不改,绿水长流,后会有期.");
                //是否点赞,
                String likeKey = StrUtil.format(ConstantUtil.VIDEO_LIKE, userId, video.getId());
                System.out.println(likeKey);
                if (stringRedisTemplate.hasKey(likeKey)) {
                    System.out.println("已点赞");
                    videoVo.setHasLiked(1);
                } else {
                    videoVo.setHasLiked(0);
                }
                //是否关注
                String focusKey = StrUtil.format(ConstantUtil.FOCUS_USER, userId, video.getUserId());
                if (stringRedisTemplate.hasKey(focusKey)) {
                    videoVo.setHasFocus(1);
                } else {
                    videoVo.setHasFocus(0);
                }
                videoVoList.add(videoVo);
            }
        }
        pageBeanVo.setItems(videoVoList);
        return pageBeanVo;
    }

    @Autowired
    private VideoMQManager videoMQManager;

    /**
     * 上传视频
     *
     * @param videoThumbnail 视频封面
     * @param videoFile      视频文件
     */
    @Logger(type = "0301")
    public void uploadVideo(MultipartFile videoThumbnail, MultipartFile videoFile) throws IOException {
        //获取用户id
        Long userId = UserHolder.getId();
        //生成一个ObjectId
        ObjectId objectId = ObjectId.get();
        //构建视频对象
        Video video = new Video();
        video.setText("青山不改,绿水长流,后会有期.");
        video.setId(objectId);
        //上传图片
        if (videoThumbnail != null && videoThumbnail.getSize() != 0) {
            String path = ossTemplate.upload(videoThumbnail.getOriginalFilename(), videoThumbnail.getInputStream());
            video.setPicUrl(path);
        }
        //上传视频,使用FastDFS分布式文件系统
        if (videoFile != null && videoFile.getSize() != 0) {
            //上传视频
            //参数一:文件的流对象
            //参数二:文件大小
            //参数三:文件后缀名
            //参数四:元数据,传空
            StorePath storePath = client.uploadFile(videoFile.getInputStream(), videoFile.getSize(),
                    FileUtil.extName(videoFile.getOriginalFilename()), null);
            //视频存储路径
            video.setVideoUrl(webServer.getWebServerUrl() + storePath.getFullPath());
        }
        //保存视频
        video.setUserId(userId);
        videoService.saveVideo(video);

        //调用方法,发送mq消息
        videoMQManager.sendMsg(video.getId().toHexString(), VideoMQManager.VIDEO_PUBLISH);
    }

    /**
     * 关注用户
     *
     * @param videoUserId 视频发布者id
     */
    public void focusOnUser(Long videoUserId) {
        //获取登录用户id
        Long loginUserId = UserHolder.getId();
        //创建关注对象
        FocusUser focusUser = new FocusUser();
        //设置对象属性
        focusUser.setUserId(loginUserId);
        focusUser.setFocusUserId(videoUserId);
        //将关注信息在redis中存储一个标志
        String key = StrUtil.format(ConstantUtil.FOCUS_USER, loginUserId, videoUserId);
        stringRedisTemplate.opsForValue().set(key, "1");
        //保存关注信息
        focusService.saveFocus(focusUser);
    }

    /**
     * 取消关注用户
     *
     * @param videoUserId 视频发布者id
     */
    public void unFollowUser(Long videoUserId) {
        //获取登录用户id
        Long loginUserId = UserHolder.getId();
        //删除关注表数据
        focusService.unFollowUser(loginUserId, videoUserId);
        //构建redis中存储的key
        String key = StrUtil.format(ConstantUtil.FOCUS_USER, loginUserId, videoUserId);
        //从redis中删除
        stringRedisTemplate.delete(key);
    }

    /**
     * 视频点赞
     *
     * @param videoId 视频id
     */
    @Logger(type = "0302")
    public Map videoLike(String videoId) {
        Long loginUserId = UserHolder.getId();
        //构建对象
        Comment comment = getComment(videoId, ConstantUtil.VIDEO_LIKE_4, loginUserId);
        //保存
        commentService.saveVideo(comment);
        //存入redis
        stringRedisTemplate.opsForValue().set(
                StrUtil.format(ConstantUtil.VIDEO_LIKE, loginUserId, videoId), videoId);
        System.out.println("=============>" + StrUtil.format(ConstantUtil.VIDEO_LIKE, loginUserId, videoId));
        //调用方法,发送mq消息,进行视频的后期推荐操作
        videoMQManager.sendMsg(videoId, VideoMQManager.VIDEO_LIKE);
        return null;
    }

    /**
     * 视频取消点赞
     *
     * @param videoId 视频id
     */
    @Logger(type = "0303")
    public Map videoDislike(String videoId) {
        Long loginUserId = UserHolder.getId();
        //构建对象
        Comment comment = getComment(videoId, ConstantUtil.VIDEO_LIKE_4, loginUserId);
        //删除
        commentService.removeVideo(comment);
        //删除redis
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.VIDEO_LIKE, loginUserId, videoId));
        //调用方法,发送mq消息,进行视频的后期推荐操作
        videoMQManager.sendMsg(videoId, VideoMQManager.VIDEO_DISLIKE);
        return null;
    }

    /**
     * 保存视频评论
     *
     * @param videoId
     * @param content
     */
    @Logger(type = "0304")
    public void saveVideoComments(String videoId, String content) {
        Long loginUserId = UserHolder.getId();
        //构建对象
        Comment comment = getComment(videoId, ConstantUtil.VIDEO_COMMENT_5, loginUserId);
        comment.setContent(content);//评论内容
        //保存评论
        commentService.saveVideo(comment);
        //调用方法,发送mq消息,进行视频的后期推荐操作
        videoMQManager.sendMsg(videoId, VideoMQManager.VIDEO_COMMENT);
    }

    /**
     * 查找视频评论列表
     *
     * @param page
     * @param pageSize
     * @param videoId  视频id
     * @return
     */
    public PageBeanVo findVideoComments(Integer page, Integer pageSize, String videoId) {
        Long loginUserId = UserHolder.getId();
        PageBeanVo pageBeanVo = commentService.findVideoCommentList(page, pageSize, videoId);
        List<Comment> items = (List<Comment>) pageBeanVo.getItems();
        List<CommentVo> commentVoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(items)) {
            for (Comment comment : items) {
                CommentVo commentVo = new CommentVo();
                UserInfo userInfo = userInfoService.findById(comment.getUserId());
                BeanUtil.copyProperties(userInfo, commentVo);
                BeanUtil.copyProperties(comment, commentVo);
                //手动封装
                commentVo.setId(comment.getId().toString());
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm");
                String creatDate = simpleDateFormat.format(comment.getCreated());
                commentVo.setCreateDate(creatDate);
                //是否点赞
                String key = StrUtil.format(
                        ConstantUtil.COMMENT_LIKE, loginUserId, comment.getId().toHexString());
                Boolean flag = stringRedisTemplate.hasKey(key);
                if (flag) {
                    commentVo.setHasLiked(1);
                }
                commentVoList.add(commentVo);
            }
        }
        pageBeanVo.setItems(commentVoList);
        return pageBeanVo;
    }

    /**
     * 视频评论点赞
     *
     * @param publishId 视频评论id
     */
    public void videoCommentLike(String publishId) {
        //获取当前登录id
        Long loginUserId = UserHolder.getId();
        //创建点赞存储对象
        Comment comment = getComment(publishId, ConstantUtil.COMMENT_LIKE_6, loginUserId);
        //保存
        commentService.saveCommentLike(comment);
        //存入redis中
        stringRedisTemplate.opsForValue().set(
                StrUtil.format(ConstantUtil.COMMENT_LIKE, loginUserId, publishId),
                publishId);
    }

    /**
     * 视频评论取消点赞
     *
     * @param publishId 视频评论id
     */
    public void videoCommentDislike(String publishId) {
        Long loginUserId = UserHolder.getId();
        //封装对象
        Comment comment = getComment(publishId, ConstantUtil.COMMENT_LIKE_6, loginUserId);
        commentService.removeCommentLike(comment);
        //删除redis中的记录
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.COMMENT_LIKE, loginUserId, publishId));
    }

    /**
     * 封装Comment对象
     *
     * @param videoId
     * @param type
     * @param loginUserId
     * @return
     */
    private Comment getComment(String videoId, Integer type, Long loginUserId) {
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(videoId));//动态id
        comment.setCommentType(type);//对视频评论
        comment.setUserId(loginUserId);//操作人id
        return comment;
    }
}
